package com.woniu108.evaluate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu108.carService.commos.dto.ProductInfoDto;
import com.woniu108.carService.commos.dto.ProductItemDto;
import com.woniu108.carService.commos.exception.WoniuException;
import com.woniu108.carService.commos.exception.evaluate.EvaluateException;
import com.woniu108.carService.commos.exception.evaluate.EvaluateExceptionCode;
import com.woniu108.carService.commos.exception.orderProduct.OrderProductException;
import com.woniu108.carService.commos.exception.orderProduct.OrderProductExceptionCode;
import com.woniu108.carService.commos.model.Result;
import com.woniu108.carService.commos.util.RedisKey;
import com.woniu108.carService.commos.util.RedisUtil;
import com.woniu108.carService.commos.util.StaticData;
import com.woniu108.evaluate.client.OrderClient;
import com.woniu108.evaluate.client.PersonClient;
import com.woniu108.evaluate.client.ProductClient;
import com.woniu108.evaluate.dto.ProductScoreDto;
import com.woniu108.evaluate.model.ProductScore;
import com.woniu108.evaluate.mapper.ProductScoreMapper;
import com.woniu108.evaluate.param.ProductScoreAddParam;
import com.woniu108.evaluate.service.ProductScoreService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu108.order.model.dto.OrderProductDto;
import com.woniu108.order.model.dto.OrderServiceDto;
import com.woniu108.order.model.form.OrderProductUpdateReviewStateForm;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 商品评分表 服务实现类
 * </p>
 *
 * @author yanxi
 * @since 2024-05-23
 */
@Service
public class ProductScoreServiceImpl extends ServiceImpl<ProductScoreMapper, ProductScore> implements ProductScoreService {
    @Resource
    private OrderClient orderClient;
    @Resource
    private ProductScoreMapper productScoreMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ProductClient productClient;
    @Resource
    private PersonClient personClient;

    @Override
    public ProductScoreDto selectProductScoreById(Integer pItemId) {
        ProductScore productScore = productScoreMapper.selectById(pItemId);
        return BeanUtil.toBean(productScore,ProductScoreDto.class);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void addScore(ProductScoreAddParam param) {
        OrderProductDto orderProductDto = orderClient.queryOrderProductByOrderNum(param.getOrderProductNum()).getData();
        //判断订单是否存在
        if(orderProductDto==null) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_NOT_EXISTED);
        }
        //订单是否属于登录用户
        if(!orderProductDto.getUserId().equals(param.getUserId())){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_REVIEW_USER_NOT_POWER);
        }
        //用户是否将该订单已经删除
        if(orderProductDto.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_DELETED)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_DELETED);
        }
        //订单是否符合发布条件
        if(orderProductDto.getOrderProductState()< StaticData.ORDER_PRODUCT_STATE_GET){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_SCORE_NOT_POWER);
        }
        //订单是否已评分过
        if(orderProductDto.getReviewState().equals(StaticData.ORDER_PRODUCT_REVIEW_STATE_FINISHED)){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_SCORE_FINISHED);
        }
        //评分是否超出范围
        if(BigDecimal.valueOf(5).compareTo(param.getScore())<0||BigDecimal.valueOf(0).compareTo(param.getScore())>0){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_SCORE_NO_FAIR);
        }
        //完成评分
        Set<Object> pInfoIds = redisUtil.sMembers(RedisKey.orderProductPInfoSet(param.getOrderProductNum()));
        for (Object pInfoId:pInfoIds){
            System.out.println(pInfoId);
            Result<ProductInfoDto> productInfoDtoResult = productClient.findProductInfoById(Integer.parseInt(pInfoId.toString()));
            if(productInfoDtoResult.getCode()!=200){
                throw new WoniuException(productInfoDtoResult.getMsg(),productInfoDtoResult.getCode());
            }
            ProductInfoDto productInfoDto = productInfoDtoResult.getData();
            ProductScore productScore = productScoreMapper.selectById(productInfoDto.getPItemId());
            productScore.setProTotalScore(productScore.getProTotalScore().add(param.getScore()));
            productScore.setProScoreNum(productScore.getProScoreNum()+1);
            productScore.setProScore(productScore.getProTotalScore().divide(BigDecimal.valueOf(productScore.getProScoreNum())));
            productScoreMapper.updateById(productScore);
        }
        //修改订单reviewState
        OrderProductUpdateReviewStateForm f = new OrderProductUpdateReviewStateForm();
        f.setOrderScore(param.getScore());
        f.setOrderProductNum(param.getOrderProductNum());
        Result<Boolean> booleanResult = orderClient.updateReviewStateByOrderProductNum(f);
        if(booleanResult.getCode()!=200){
            throw new WoniuException(booleanResult.getMsg(),booleanResult.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean addProductScoreByPItemId(Integer pItemId) {
        Result<ProductItemDto> productItemDtoResult= productClient.findProductItemByItemId(pItemId);
        if(productItemDtoResult.getCode()!=200){
            throw new WoniuException(productItemDtoResult.getMsg(),productItemDtoResult.getCode());
        }
        //判断商品是否存在
        ProductItemDto productItemDto = productItemDtoResult.getData();
        if(productItemDto==null){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_PRODUCT_NOT_EXISTED);
        }
        //判断是否早已创建
        ProductScore productScore = productScoreMapper.selectById(productItemDto.getPItemId());
        if(productScore!=null){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_SCORE_EXISTED);
        }

        productScore.setPItemId(productItemDto.getPItemId());
        productScore.setProScoreNum(0);
        productScore.setProScore(BigDecimal.valueOf(0));
        productScore.setProTotalScore(BigDecimal.valueOf(0));
        //执行创建
        productScoreMapper.insert(productScore);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean delProductScore(Integer pItemId) {
        Result<ProductItemDto> productItemDtoResult= productClient.findProductItemByItemId(pItemId);
        if(productItemDtoResult.getCode()!=200){
            throw new WoniuException(productItemDtoResult.getMsg(),productItemDtoResult.getCode());
        }
        //判断商品是否存在
        ProductItemDto productItemDto = productItemDtoResult.getData();
        if(productItemDto!=null&&!productItemDto.getProState().equals(StaticData.PRODUCT_ITEM_STATE_DELETE)){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_PRODUCT_EXISTED);
        }
        //判断是否未创建
        ProductScore productScore = productScoreMapper.selectById(productItemDto.getPItemId());
        if(productScore==null){
            throw new EvaluateException(EvaluateExceptionCode.EVALUATE_SCORE_NO_EXISTED);
        }
        //执行删除
        productScoreMapper.deleteById(productScore.getPItemId());
        return true;
    }

    @Override
    public List<ProductScoreDto> selectAllProductScore() {
        QueryWrapper<ProductScore> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("pro_total_score");
        queryWrapper.orderByDesc("pro_score_num");
        List<ProductScore> productScores = productScoreMapper.selectList(queryWrapper);
        if(productScores.size()>0){
            ArrayList<ProductScoreDto> productScoreDtos = new ArrayList<>();
            for (ProductScore productScore:productScores){
                ProductScoreDto productScoreDto = selectProductScoreById(productScore.getPItemId());
                productScoreDtos.add(productScoreDto);
            }
            return productScoreDtos;
        }else {
            return null;
        }
    }
}
